package cn.flying.cloud.task.core.quartz.job;

import javax.annotation.Resource;

import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import org.quartz.DisallowConcurrentExecution;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.PersistJobDataAfterExecution;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;

import cn.flying.cloud.base.common.utils.Ft;
import cn.flying.cloud.base.common.utils.date.DateTimeUtil;
import cn.flying.cloud.task.core.context.JobHandlerCache;
import cn.flying.cloud.task.core.handler.AbstractJobHandler;
import cn.flying.cloud.task.core.model.JobContext;
import cn.flying.cloud.task.core.quartz.constants.TaskConstant;
import cn.flying.cloud.task.core.quartz.exception.TaskException;
import cn.flying.cloud.task.entity.TaskJobInfo;

/**
 * @author: admin
 * @date: 2025年03月12日 20:19
 * @version: 1.0
 */
@DisallowConcurrentExecution
@PersistJobDataAfterExecution
@Component
public class ScheduleJobExecution extends QuartzJobBean {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Resource
    private JobHandlerCache jobHandlerCache;

    /**
     * @param context
     * @throws JobExecutionException
     */
    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        TaskJobInfo jobInfo = new TaskJobInfo();

        JobDataMap jobDataMap = context.getMergedJobDataMap();
        BeanUtils.copyProperties(jobDataMap.get(TaskConstant.JOB_PERSISTENCE), jobInfo);

        // Job执行参数
        Map<String, Object> jobParam = new HashMap<>();

        LocalDate jobDate = LocalDate.now();
        Object o = Ft.LocalCache.get(jobInfo.getJobGroup() + ":" + jobInfo.getJobName() + ":" + "jobParam");
        if (o != null) {
            Map<String, Object> map = Ft.JSON.parseToMap((String) o);
            // 这里还是get一下，防止被null覆盖
            Object date = map.get("jobDate");
            if (date != null) {
                jobDate = Ft.DateTime.parseLocalDate((String) date, "yyyy-MM-dd");
            }

            jobParam.putAll(map);
        }

        String serialNo = Ft.DateTime.formatLocalDateTime(LocalDateTime.now(), DateTimeUtil.DATE_TIME_FORMAT_1);
        jobParam.put("serialNo", serialNo);
        jobParam.put("jobType", jobInfo.getJobType());
        jobParam.put("jobDate", jobDate);


        JobContext jobContext = getJobContext(jobInfo, jobDate, jobParam);

        AbstractJobHandler jobHandler = jobHandlerCache.getJobHandlerCache().get(jobContext.getJobName());
        if (jobHandler == null) {
            throw new TaskException("执行的任务不存在！");
        }
        // 调用 Bean 的 executeJob 方法
        jobHandler.executeJob(jobContext);
    }

    private JobContext getJobContext(TaskJobInfo jobInfo, LocalDate jobDate, Map<String, Object> jobParam) {
        JobContext jobContext = new JobContext();
        jobContext.setServiceName(jobInfo.getServiceName());
        jobContext.setJobDate(jobDate);
        jobContext.setJobName(jobInfo.getJobName());
        jobContext.setJobType(jobInfo.getJobType());
        jobContext.setJobGroup(jobInfo.getJobGroup());
        jobContext.setJobDesc(jobInfo.getJobDesc());
        jobContext.setJobParam(jobParam);
        jobContext.setHost(getHost());
        jobContext.setRemark(jobInfo.getRemark());
        jobContext.setTenantId(jobInfo.getTenantId());
        return jobContext;
    }

    private String getHost() {
        try {
            // 遍历所有网络接口
            Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
            while (interfaces.hasMoreElements()) {
                NetworkInterface iface = interfaces.nextElement();
                // 过滤掉127.0.0.1和非活动接口
                if (iface.isLoopback() || !iface.isUp()) {
                    continue;
                }

                // 遍历所有IP地址
                Enumeration<InetAddress> addresses = iface.getInetAddresses();
                while (addresses.hasMoreElements()) {
                    InetAddress addr = addresses.nextElement();

                    // 排除IPv6地址，只保留IPv4
                    if (addr instanceof Inet4Address) {
                        return addr.getHostAddress();
                    }
                }
            }
        } catch (SocketException e) {
            throw new RuntimeException(e);
        }
        return "127.0.0.1";
    }

    /**
     * 手动补偿处理
     *
     * @param jobInfo
     * @param serialNo
     * @param param
     * @param host
     */
    public void resolveJob(TaskJobInfo jobInfo, String serialNo, String param, String host) {
//        // Job执行参数
//        Map<String, Object> jobParam = new HashMap<>();
//        if (Ft.String.isBlank(serialNo)) {
//            serialNo = Ft.DateTime.formatLocalDateTime(LocalDateTime.now(), DateTimeUtil.DATE_TIME_FORMAT_1);
//        }
//        jobParam.put("serialNo", serialNo);
//        jobParam.put("jobType", jobInfo.getJobType());
//        jobParam.put("jobDate", LocalDate.now());
//
//        TaskJobLog log = setLog(jobInfo, host, serialNo);
//        log.setJobDate(LocalDate.now());
//        if (param != null) {
//            Map<String, Object> map = Ft.JSON.parseToMap(param);
//            log.setJobDate(Ft.DateTime.parseLocalDate((String) map.get("jobDate"), "yyyy-MM-dd"));
//            jobParam.putAll(map);
//        }
//        taskJobLogService.createObj(log);
//
//        Map<String, Object> body = setRequestBody(jobInfo, log);
//        body.put("jobParam", Ft.JSON.serializer(jobParam));
//
//        // 构建服务实例的 URL
//        String url = host + "/job/resolve";
//        // 发起 HTTP 请求
//        call(url, log, body);
    }

}
